package org.example.mock;


import lombok.extern.slf4j.Slf4j;
import org.example.bean.CountryAnnualBoxOffice;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.*;
import java.util.*;

@Slf4j
public class CountryAnnualBoxOfficeGenerator {
    private static final String DB_URL = "jdbc:mysql://192.168.10.102/changchengfilm?requireSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "000000";
    private static final int BATCH_SIZE = 50;
    private static final int TOTAL_RECORDS = 50; // 生成50条数据

    private static final Random RANDOM = new Random();
    private static final List<String> COUNTRIES = Arrays.asList(
            "中国", "美国", "英国", "法国", "德国", "日本", "韩国", "印度", "俄罗斯", "加拿大",
            "澳大利亚", "意大利", "西班牙", "巴西", "墨西哥"
    );
    private static final int START_YEAR = 2020;
    private static final int END_YEAR = 2024;

    public static void main(String[] args) {
        log.info("开始生成{}条国家年度票房数据", TOTAL_RECORDS);

        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            clearExistingData(conn);
            List<CountryAnnualBoxOffice> dataList = generateData();
            insertToDatabase(dataList, conn);
            log.info("数据生成完成");
        } catch (SQLException e) {
            log.error("数据库操作失败", e);
        }
    }

    private static void clearExistingData(Connection conn) throws SQLException {
        try (Statement stmt = conn.createStatement()) {
            stmt.executeUpdate("TRUNCATE TABLE ads_country_annual_box_office");
        }
    }

    private static List<CountryAnnualBoxOffice> generateData() {
        List<CountryAnnualBoxOffice> dataList = new ArrayList<>(TOTAL_RECORDS);
        Set<String> uniqueKeys = new HashSet<>(); // 确保 countryName + year 唯一

        for (int i = 0; i < TOTAL_RECORDS; i++) {
            String countryName = COUNTRIES.get(RANDOM.nextInt(COUNTRIES.size()));
            int year = START_YEAR + RANDOM.nextInt(END_YEAR - START_YEAR + 1);
            String key = countryName + "_" + year;

            // 确保唯一性
            while (!uniqueKeys.add(key)) {
                countryName = COUNTRIES.get(RANDOM.nextInt(COUNTRIES.size()));
                year = START_YEAR + RANDOM.nextInt(END_YEAR - START_YEAR + 1);
                key = countryName + "_" + year;
            }

            // 国家票房规模系数（简化版）
            double countryFactor = 0.3 + RANDOM.nextDouble() * 0.9; // 0.3-1.2

            int totalMovies = (int) (50 + RANDOM.nextInt(200) * countryFactor); // 50-250部
            BigDecimal totalBoxOffice = generateBoxOffice(countryFactor, year);
            BigDecimal avgBoxOffice = totalBoxOffice.divide(BigDecimal.valueOf(totalMovies), 2, RoundingMode.HALF_UP);
            BigDecimal maxBoxOffice = totalBoxOffice.multiply(BigDecimal.valueOf(0.1 + RANDOM.nextDouble() * 0.2)).setScale(2, RoundingMode.HALF_UP);
            BigDecimal minBoxOffice = totalBoxOffice.multiply(BigDecimal.valueOf(0.0001 + RANDOM.nextDouble() * 0.0009)).setScale(2, RoundingMode.HALF_UP);
            BigDecimal growthRate = calculateGrowthRate(dataList, countryName, year);

            dataList.add(CountryAnnualBoxOffice.builder()
                    .countryId(COUNTRIES.indexOf(countryName) + 1)
                    .countryName(countryName)
                    .year(year)
                    .totalMovies(totalMovies)
                    .totalBoxOffice(totalBoxOffice)
                    .avgMovieBoxOffice(avgBoxOffice)
                    .maxBoxOffice(maxBoxOffice)
                    .minBoxOffice(minBoxOffice)
                    .boxOfficeGrowthRate(growthRate)
                    .build());
        }

        return dataList;
    }

    private static BigDecimal generateBoxOffice(double countryFactor, int year) {
        // 基础票房（亿元），考虑年份增长趋势
        double baseBoxOffice = (5 + RANDOM.nextDouble() * 95) * (1 + (year - START_YEAR) * 0.05);
        return new BigDecimal(baseBoxOffice * 10000).setScale(2, RoundingMode.HALF_UP); // 转换为万元
    }

    private static BigDecimal calculateGrowthRate(List<CountryAnnualBoxOffice> dataList, String countryName, int year) {
        if (year <= START_YEAR) return null; // 起始年份没有同比数据

        // 查找去年数据
        Optional<CountryAnnualBoxOffice> lastYearData = dataList.stream()
                .filter(d -> d.getCountryName().equals(countryName) && d.getYear() == year - 1)
                .findFirst();

        if (lastYearData.isEmpty() || lastYearData.get().getTotalBoxOffice().compareTo(BigDecimal.ZERO) == 0) {
            return null;
        }

        // 计算同比增长率
        BigDecimal current = dataList.stream()
                .filter(d -> d.getCountryName().equals(countryName) && d.getYear() == year)
                .findFirst()
                .map(CountryAnnualBoxOffice::getTotalBoxOffice)
                .orElse(BigDecimal.ZERO);

        BigDecimal lastYear = lastYearData.get().getTotalBoxOffice();
        return current.subtract(lastYear)
                .divide(lastYear, 4, RoundingMode.HALF_UP)
                .multiply(BigDecimal.valueOf(100))
                .setScale(2, RoundingMode.HALF_UP);
    }

    private static void insertToDatabase(List<CountryAnnualBoxOffice> dataList, Connection conn) throws SQLException {
        String sql = "INSERT INTO ads_country_annual_box_office " +
                "(country_id, country_name, year, total_movies, total_box_office, " +
                "avg_movie_box_office, max_box_office, min_box_office, box_office_growth_rate) " +
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";

        try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
            conn.setAutoCommit(false);

            for (int i = 0; i < dataList.size(); i++) {
                CountryAnnualBoxOffice data = dataList.get(i);
                pstmt.setInt(1, data.getCountryId());
                pstmt.setString(2, data.getCountryName());
                pstmt.setInt(3, data.getYear());
                pstmt.setInt(4, data.getTotalMovies());
                pstmt.setBigDecimal(5, data.getTotalBoxOffice());
                pstmt.setBigDecimal(6, data.getAvgMovieBoxOffice());
                pstmt.setBigDecimal(7, data.getMaxBoxOffice());
                pstmt.setBigDecimal(8, data.getMinBoxOffice());

                if (data.getBoxOfficeGrowthRate() != null) {
                    pstmt.setBigDecimal(9, data.getBoxOfficeGrowthRate());
                } else {
                    pstmt.setNull(9, java.sql.Types.DECIMAL);
                }

                pstmt.addBatch();
            }

            pstmt.executeBatch();
            conn.commit();
        } catch (SQLException e) {
            conn.rollback();
            throw e;
        }
    }
}